package ru.spbau.bytecode.graph;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.font.FontRenderContext;
import java.awt.geom.Rectangle2D;

import ru.spbau.bytecode.geom.Segment;

public class Vertex {
	
	private static final int OFFSET = 5;

	private final String name;
	
	protected boolean catched = false;
	protected Point location = new Point(0, 0);
	protected boolean visible = true;
	protected Dimension size = new Dimension(0, 0);
	
//	private final Color color = new Color(164, 211, 238);
	private final Color color = new Color(202, 225, 255);
	
	protected Rectangle bounds =
		new Rectangle(0, 0, Integer.MAX_VALUE, Integer.MAX_VALUE);
	
	
	public Vertex(String name) {
		this.name = name;
		
		// TODO get current font
		Font f = new Font("Serif", Font.PLAIN, 15);
		
		Rectangle2D rect = f.getStringBounds(getName(),
				new FontRenderContext(null, false, false));
		
		size = new Dimension(rect.getBounds().width + OFFSET, rect.getBounds().height);
	}
	
	public String getName() {
		return name;
	}
	
	@Override
	public boolean equals(Object o) {
		if (!(o instanceof Vertex)) {
			return false;
		}
		
		Vertex v = (Vertex) o;
		return name.equals(v.name);
	}
	
	@Override
	public int hashCode() {
		return name.hashCode();
	}
	
	@Override
	public String toString() {
		return name;
	}
	
	
	public void setBounds(Rectangle bounds) {
		this.bounds = bounds;
	}
	
	public Rectangle getBounds() {
		return bounds;
	}
	
	public void move(int dx, int dy) {
		location.x += dx;
		location.y += dy;
		
		if (location.x <  bounds.x + OFFSET) {
			location.x = bounds.x + OFFSET;
		}
		if (location.x + size.width > bounds.x + bounds.width - OFFSET) {
			location.x = bounds.x + bounds.width - size.width - OFFSET;
		}
		if (location.y < bounds.y + OFFSET) {
			location.y = bounds.y + OFFSET;
		}
		if (location.y + size.height > bounds.y + bounds.height - OFFSET) {
			location.y = bounds.y + bounds.height - size.height - OFFSET;
		}
	}
	
	public Point getLocation() {
		return location;
	}
	
	public void setLocation(Point location) {
		this.location = location;
	}

	public boolean isCatched() {
		return catched;
	}

	public void setCatched(boolean catched) {
		this.catched = catched;
	}
	
	public boolean pointInside(Point p) {
		return p.x >= location.x && p.x <= location.x + size.width && 
				p.y >= location.y && p.y <= location.y + size.height;
	}
	
	public boolean isVisible() {
		return visible;
	}
	
	public void invert() {
		visible = !visible;
	}
	
	public void setVisible(boolean visible) {
		this.visible = visible;
	}
	
	public Dimension getSize() {
		return size;
	}
	
	public void setSize(Dimension size) {
		this.size = size;
	}
	
	public Point getCenter() {
		return new Point(location.x + size.width / 2, location.y + size.height / 2);
	}
	
	public Point getEdgeEndpoint(Segment edge) {
		Point leftTop = new Point(location.x, location.y);
		Point leftBottom = new Point(location.x, location.y + size.height);
		Point rightTop = new Point(location.x + size.width, location.y);
		Point rightBottom = new Point(location.x + size.width, location.y + size.height);
		
		Segment left = new Segment(leftTop, leftBottom);
		if (left.intersects(edge)) {
			return left.getIntersection(edge);
		}
		Segment top = new Segment(leftTop, rightTop);
		if (top.intersects(edge)) {
			return top.getIntersection(edge);
		}
		Segment right = new Segment(rightTop, rightBottom);
		if (right.intersects(edge)) {
			return right.getIntersection(edge);
		}
		Segment bottom = new Segment(leftBottom, rightBottom);
		if (bottom.intersects(edge)) {
			return bottom.getIntersection(edge);
		}
		return null;
	}
	
	public void draw(Graphics g) {
		if (visible) {
			Color currentColor = g.getColor();
			g.setColor(color);
			g.fillRect(location.x, location.y, size.width, size.height);
			g.setColor(currentColor);
			g.drawRect(location.x, location.y, size.width, size.height);
			g.drawString(getName(), location.x + OFFSET,
						location.y + size.height - OFFSET);
		}
	}
}
